import 'monaco-editor/esm/vs/basic-languages/bat/bat.contribution';
import "monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution";
import 'monaco-editor/esm/vs/basic-languages/sql/sql.contribution';
import "monaco-editor/esm/vs/language/json/monaco.contribution";
import React, { useEffect, useRef, useState } from "react";
import { createRoot } from "react-dom/client";
// import * as monaco from "monaco-editor/esm/vs/editor/editor.api";
import * as monaco from "monaco-editor/esm/vs/editor/edcore.main";
import editorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker";
import jsonWorker from "monaco-editor/esm/vs/language/json/json.worker?worker";
import "tailwindcss/tailwind.css";

import { format as formatSql } from 'sql-formatter';

import { formatLogStr } from './format';

self.MonacoEnvironment = {
  getWorker: (_, label) => {
    if (label === "json") {
      return new jsonWorker();
    }

    return editorWorker();
  },
};

const Edit = function ({ className, setCode }) {
  const editRef = useRef();
  const [edit, setEdit] = useState();

  useEffect(() => {
    if (editRef.current && !edit) {
      const editIns = monaco.editor.create(editRef.current, {
        value: "",
        language: "sql",
        mimeType: "text/plain",
        automaticLayout: true, // 自动布局
        minimap: {
          enabled: false,
        },
      });
      editIns.onDidChangeModelContent((e) => {
        const code = editIns.getValue();
        setCode(code);
      });
      setEdit(editIns);
    }
  }, [editRef.current]);

  return <div className={`${className || ""}`} ref={editRef}></div>;
};

const View = function ({ className, code }) {
  const editRef = useRef();
  const [edit, setEdit] = useState();
  const [syncError, setSyncError] = useState();
  const [formatedCode, setFormatedCode] = useState();

  useEffect(() => {
    let ast;
    try {
      if (code) {
        ast = formatLogStr(code);
        setSyncError(undefined);
      }
    } catch (error) {
      setSyncError(error?.message);
    }
    try{
      setFormatedCode(formatSql(ast || ""))
    }catch{
      setFormatedCode(ast);
    }
  }, [code]);

  useEffect(() => {
    if (editRef.current && !edit) {
      const editIns = monaco.editor.create(editRef.current, {
        value: "",
        language: "sql",
        // mimeType: "text/plain",
        automaticLayout: true, // 自动布局
        minimap: {
          enabled: false,
        },
        readOnly: true,
        formatOnType: true,
        formatOnPaste: true,
      });
      setEdit(editIns);
    }
  }, [editRef.current]);

  useEffect(() => {
    if (formatedCode && edit) {
      edit.setValue(formatedCode);
    } else if (syncError && edit) {
      edit.setValue(JSON.stringify(syncError));
    }
  }, [formatedCode, edit]);

  return <div className={`${className || ""}`} ref={editRef}></div>;
};

const App = function () {
  const [code, setCode] = useState("");
  return (
    <div className="flex flex-col border-r border-r-gray-300 h-full">
      <Edit
        className="flex-auto h-1/3 box-border"
        setCode={setCode}
      />
      <View className="flex-auto h-2/3 border-t-2 border-t-gray-300 box-border" code={code} />
    </div>
  );
};

const root = createRoot(document.getElementById("app"));
root.render(<App />);
